﻿package igz.fleaxy.util {
	
	/**
	 * @author Intelygenz | www.intelygenz.com
	 */
	public class DataTableUtil {
		
		static public var $COLUMNS_LABEL	: String = "columns";
		static public var $ROWS_LABEL		: String = "rows";
		
		public function DataTableUtil() {
			
		}

		/**
		 * 
		 * @param	p_dataTable
		 * @return
		 */
		static public function $IsDataTable(p_dataTable:Object):Boolean {
			if ( p_dataTable != null 
			  && p_dataTable.hasOwnProperty( $COLUMNS_LABEL ) 
			  && p_dataTable.hasOwnProperty( $ROWS_LABEL ) 
			  ) {
				return true;
			}
			else {
				return false;
			}
		}
		
		/**
		 * 
		 * @param	p_dataTable
		 * @param	p_columnName
		 * @return
		 */
		static public function $ColumnIndex(p_dataTable:Object, p_columnName:String) : int {
			if ( !$IsDataTable(p_dataTable) ) return -1;
			else return p_dataTable[$COLUMNS_LABEL].indexOf(p_columnName);
		}

		/**
		 * 
		 * @param	p_dataTable
		 * @param	p_columnName
		 * @param	p_findValue
		 * @return
		 */
		static public function $IndexOf(p_dataTable:Object, p_columnName:String, p_findValue:String ) : int {
			var rowIdx:int = -1;
			var colIdx:int = $ColumnIndex(p_dataTable, p_columnName);
			if (colIdx != -1) {
				var f:uint = 0, F:uint = p_dataTable[$ROWS_LABEL].length;
				for (f = 0; f < F; f++) {
					if ( p_dataTable[$ROWS_LABEL][f][colIdx] == p_findValue ) {
						rowIdx = f;
						break;
					}
				}
			}
			return rowIdx;
		}

		/**
		 * 
		 * @param	p_dataTable
		 * @param	p_columnName
		 * @param	p_index
		 * @return
		 */
		static public function $ValueOf(p_dataTable:Object, p_columnName:String, p_index:uint = 0) : String {
			var colIdx:int = $ColumnIndex(p_dataTable, p_columnName);
			return p_dataTable[$ROWS_LABEL][p_index][colIdx];
		}
		
		/**
		 * 
		 * @param	p_dataTable
		 * @param	p_findColumnName
		 * @param	p_findValue
		 * @param	p_returnColumnName
		 */
		static public function $ValueIf(p_dataTable:Object, p_findColumnName:String, p_findValue:String, p_returnColumnName:String ) : String {
			return $ValueOf( p_dataTable, p_returnColumnName, $IndexOf(p_dataTable, p_findColumnName, p_findValue) );
		}

		/**
		 * Devuelve la suma de los registros de la columna indicada
		 */
		static public function $SumColumn(p_dataTable:Object, p_columnName:String) : Number {
			var sum:Number = 0;
			var colIdx:int = $ColumnIndex(p_dataTable, p_columnName);
			if (colIdx != -1) {
				var f:uint = 0, F:uint = p_dataTable[$ROWS_LABEL].length;
				for (f = 0; f < F; f++) {
					sum += Number(p_dataTable[$ROWS_LABEL][f][colIdx]);
				}
			}
			return sum;
		}
		
		/**
		 * Devuelve el número de registros
		 */
		static public function $Length ( p_dataTable:Object ) : uint {
			return p_dataTable[$ROWS_LABEL].length;
		}
		
		/**
		 * Devuelve el número de columnas
		 */
		static public function $NumColumns ( p_dataTable:Object ) : uint {
			return p_dataTable[$COLUMNS_LABEL].length;
		}
		
		/**
		 * Devuelve todos los registros
		 */
		static public function $GetRows ( p_dataTable:Object ) : Array {
			return p_dataTable[$ROWS_LABEL] as Array;
		}
		
		/**
		 * Devuelve el registro deseado
		 */
		static public function $GetRow ( p_dataTable:Object, p_index:int ) : Array {
			return (p_dataTable[$ROWS_LABEL] as Array)[p_index];
		}

		/**
		 * Devuelve un array con los registros de la columna indicada
		 */
		static public function $GetColumn( p_dataTable:Object, p_columnName:String ) : Array {
			var columnArray : Array;
			var colIdx : int = $ColumnIndex( p_dataTable, p_columnName );
			if ( colIdx != -1 ) {
				var numRows : Number = $Length(p_dataTable);
				columnArray = new Array( numRows );
				var f : uint;
				for ( f = 0; f < numRows; f++ ) {
					columnArray[f] = p_dataTable[$ROWS_LABEL][f][colIdx];
				}
			}
			return columnArray;
		}
		
		/**
		 * Devuelve un array con los registros de la columna en la posición indicada
		 */
		static public function $GetColumnAt( p_dataTable:Object, p_index:uint ) : Array {
			var numRows : Number = $Length(p_dataTable);
			var columnArray : Array = new Array( numRows );
			
			var f : uint;
			for ( f = 0; f < numRows; f++ ) {
				columnArray[f] = p_dataTable[$ROWS_LABEL][f][p_index];
			}
			
			return columnArray;
		}
		
		/**
		 * Devuelve un array con la columna indicada ordenada
		 */
		static public function $SortColumn ( p_dataTable:Object, p_columnName:String, p_settings:Object = null ) : Array {
			var sortSettings : Object = {
				 "dateFormat" : DateTimeFormat.DEFAULT_DATE // Usado si la columna es una fecha
				,"returnIndex" : false // Devuelve un array que representa las posiciones de los elementos ordenados
				,"descending" : false
				,"caseInsensitive" : false
				,"uniqueSort" : false
			};
			ObjectUtil.$Merge( p_settings, sortSettings );
			
			var arraySortOptions : uint;
			if ( sortSettings["returnIndex"] ) {
				arraySortOptions = Array.RETURNINDEXEDARRAY;
			}
			if ( sortSettings["descending"] ) {
				arraySortOptions = arraySortOptions | Array.DESCENDING;
			}
			if ( sortSettings["caseInsensitive"] ) {
				arraySortOptions = arraySortOptions | Array.CASEINSENSITIVE;
			}
			if ( sortSettings["uniqueSort"] ) {
				arraySortOptions = arraySortOptions | Array.UNIQUESORT;
			}
			
			var columnArray : Array = $GetColumn( p_dataTable, p_columnName );

			var columnLength : uint = columnArray.length;
			if ( columnLength != 0 ) {
				var numericSort : Boolean = true;
				var f : uint = 0;
				var value: String;
				while ( numericSort && f < columnLength ) {
					value = columnArray[ f++ ];//.replace(",", ".");
					if ( value != "" && isNaN( Number(value) ) ) {
						numericSort = false;
					}
				}

				if ( numericSort ) {
					columnArray = columnArray.sort( Array.NUMERIC | arraySortOptions );
				}
				else {
					// string or date
					var dateFormat : String = sortSettings["dateFormat"];
					var valueDate : Date;
					var dateSort : Boolean = true; f = 0;
					var sortedArray : Array = new Array(columnLength);
					while ( dateSort && f < columnLength ) {
						try {
							valueDate = DateTimeUtil.$ToDate( columnArray[f], dateFormat );
							sortedArray[f] = valueDate.time;
							f++;
						}
						catch ( e:Error ) {
							dateSort = false;
						}
					}
					
					if ( dateSort ) {
						sortedArray = sortedArray.sort( Array.NUMERIC | Array.RETURNINDEXEDARRAY | arraySortOptions);
						if ( sortSettings["returnIndex"] ) {
							columnArray = sortedArray;
						}
						else {
							var newArray : Array = new Array(columnLength);
							for ( f = 0; f < columnLength; f++ ) {
								newArray[f] = columnArray[ sortedArray[f] ];
							}
							columnArray = newArray;
						}
					}
					else {
						// string
						columnArray = columnArray.sort( arraySortOptions );
					}
				}
			}

			return columnArray;
		}
	}
	
}